feat(wiki): kb.backlinks - expose the wiki link graph as a method - #734
Open
joaovictor91123 wants to merge 3 commits into
Open
feat(wiki): kb.backlinks - expose the wiki link graph as a method#734joaovictor91123 wants to merge 3 commits into
joaovictor91123 wants to merge 3 commits into
Conversation
wiki_render.backlinks() already computed the inbound-link map internally, used by render_moc to rank pages, but nothing exposed it - no MCP tool, no JSONL handler, no CLI command, only reachable indirectly by parsing vouch render-wiki's rendered markdown output. kb.neighbors looks adjacent but is entirely disjoint - it walks the claim/entity/relation graph, never [[wikilink]] edges between pages. add outbound_links() as a small new sibling to backlinks() in wiki_render.py (titles a page's own body links to, resolved and deduplicated, self-links dropped), and page_links() combining both directions for one page. register kb.backlinks the same four ways every other kb.* method is: mcp kb_backlinks, jsonl kb.backlinks, capabilities.py, cli vouch backlinks [page_id]. with a page_id, returns that page's inbound + outbound titles; without, the full inbound map. unknown page_id uses the same not-found contract kb.neighbors already has for an unknown root node. archived pages are excluded from the checked set and treated as unresolvable link targets, matching render-wiki's own vouchdev#695 exclusion policy - a link to an archived page is exactly as dead as a link to nothing. read-only, like every other wiki_render view - never proposes, writes, or mutates, so it doesn't touch proposals.py, lifecycle.py, or the review gate. Closes vouchdev#732
test_hot_memory_universal_coverage asserts every kb.* method is either in HOT_MEMORY_COVERED or explicitly excluded in HOT_MEMORY_EXCLUDED - a new method with neither fails the suite. kb.backlinks landed with neither, breaking CI. excluded with the same reason kb.neighbors already carries: a graph slice, out of scope for the recency sidebar.
…path diff-coverage flagged server.py:341-347 (kb_backlinks' whole mcp tool body - only exercised indirectly via jsonl/cli, never called directly) and cli.py:3509-3510 (the `vouch backlinks` no-arg full-map branch - only the single-page case had a cli test). add a direct server.kb_backlinks() test covering single-page, full-map, and unknown-page cases (matching test_explain_ranking.py's test_mcp_surface_serves_explain_ranking pattern), and a CliRunner test for `vouch backlinks` with no page id.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
New
kb.backlinksmethod exposing the wiki's[[wikilink]]graph, on allfour surfaces (MCP
kb_backlinks, JSONLkb.backlinks,capabilities.py, CLIvouch backlinks [page_id]):page_id: that page's inbound and outbound link titles.Inbound reuses the existing
wiki_render.backlinks(); outbound is asmall new sibling,
wiki_render.outbound_links(), walking the page's ownbody (resolved, deduplicated, self-links dropped — same conventions as
backlinks()).page_id: the full inbound map —wiki_render.backlinks()exposed directly.
page_id→ the same "not found" contractkb.neighborsalreadyuses for an unknown root node.
Why
wiki_render.backlinks()already computed the inbound-link map internally(used by
render_moc's ranking), but nothing exposed it as agent-facingdata — no MCP tool, no JSONL handler, no CLI command. The only way to see
it was parsing
vouch render-wiki's rendered markdown output.kb.neighborslooks adjacent but is entirely disjoint: it walks the claim/entity/relation
graph (
graph.find_neighbors); greppedgraph.pyand confirmed zerowikilink handling there. The two graphs don't overlap in edges, sources, or
node kinds.
Closes #732
Roadmap 1.4: "Backlinks:
[[wikilinks]]are validated today, thendiscarded; persist the link graph and render it." This ships the "render it
as data" half. The "persist" half is deliberately not done here —
wiki_render.py's own docstring already frames these as "regenerableviews... like the SQLite index, not authored knowledge," and adding real
on-disk persistence (cache invalidation, whether
kb.index_rebuildshouldtouch it, etc.) is a bigger, separate design question than exposing the
already-computed view as a method.
What might break
Nothing for users with an existing
.vouch/directory — purely additive:a new method, two new pure functions in
wiki_render.py, no object modelor on-disk shape change. Fully read-only, like every other
wiki_renderview — never proposes, writes, or mutates, so it doesn't touch
proposals.py,lifecycle.py,storage.py, or the review gate.Archived pages are excluded from the checked set and treated as
unresolvable link targets — this matches
render-wiki's existing (#695)exclusion policy exactly (a link to an archived page is exactly as dead as
a link to nothing), so it's not a new precedent.
VEP
Not applicable — no object model, on-disk layout, bundle format, or
audit-log shape change. A new read-only method over an already-computed
derived view, same shape as
kb.neighbors.Tests
make check-equivalent: ruff clean (src+tests); mypyclean;
tests/test_capabilities.py(four-surface parity),tests/test_wiki_render.py,tests/test_health.py,tests/test_cli.pyall passtests/test_wiki_render.pywith12 new cases:
outbound_links/page_linksunit tests (self-linkexclusion, dedup, unresolved links, unknown page), plus JSONL
envelope tests (single page, full map, unknown page error, archived
page exclusion) and CLI smoke tests (
CliRunner)CHANGELOG.mdupdated under## [Unreleased]